#include "AdminManager.h"
#include "Channel.h"
#include "User.h"
#include "Buffer.h"
#include "AdminSerializer.h"
#include "AdminEventManager.h"
#include "HostRight.h"
#include "ChannelRight.h"
#include "Header.h"
#include <string>


using namespace AgoraClient;

AdminManager *AdminManager::_instance = 0;

void	AdminManager::Init(Agora *agora)
{
	if (AdminManager::_instance == 0)
	{
		AdminManager::_instance = new AdminManager(agora);
	}
}

AdminManager *AdminManager::GetAdminManager()
{
	return AdminManager::_instance;
}


AdminManager::AdminManager(Agora* agora)
: _agora(agora), _curUserHostRight(0)
{
	this->_interpreteServerMessageFct[TREATERROR] = &AdminManager::TreatError;
	this->_interpreteServerMessageFct[GETALLCHANNEL] = &AdminManager::LoadAllChannel;
	this->_interpreteServerMessageFct[CREATECHANNEL] = &AdminManager::AddAChannel;
	this->_interpreteServerMessageFct[JOINCHANNEL] = &AdminManager::OnUserJoinChannel;
	this->_interpreteServerMessageFct[GETALLUSER] = &AdminManager::LoadAllUser;
	this->_interpreteServerMessageFct[GETHOSTRIGHT] = &AdminManager::LoadHostRight;
	this->_interpreteServerMessageFct[GETCHANNELRIGHT] = &AdminManager::LoadChannelRight;
	this->_interpreteServerMessageFct[GETUSERHOSTRIGHT] = &AdminManager::OnUserHostRightReceived;
	this->_interpreteServerMessageFct[GETUSERCHANNELRIGHT] = &AdminManager::OnUserChannelRightReceived;
	this->_interpreteServerMessageFct[EDITUSERHOSTRIGHT] = &AdminManager::OnUserHostRightEdited;
	this->_interpreteServerMessageFct[EDITUSERCHANNELRIGHT] = &AdminManager::OnUserChannelRightEdited;
	this->_interpreteServerMessageFct[DELETECHANNEL] = &AdminManager::OnChannelDeleted;
	this->_interpreteServerMessageFct[DISCONNECT] = &AdminManager::OnUserDisconnection;
	this->_interpreteServerMessageFct[CONNECT] = &AdminManager::OnUserConnection;
	this->_interpreteServerMessageFct[CREATEUSER] = &AdminManager::OnUserCreated;
	this->_interpreteServerMessageFct[DELETEUSER] = &AdminManager::OnUserDeleted;
	this->_interpreteServerMessageFct[KICKUSER] = &AdminManager::OnUserKicked;
	this->_interpreteServerMessageFct[KICKUSERSERVER] = &AdminManager::OnUserKickedFromServer;
	this->_interpreteServerMessageFct[BANUSER] = &AdminManager::OnUserBanned;
	this->_interpreteServerMessageFct[BANUSERSERVER] = &AdminManager::OnUserBannedFromServer;
	this->_interpreteServerMessageFct[GETBANUSERLIST] = &AdminManager::OnUserBannedListReceived;
	this->_interpreteServerMessageFct[GETBANUSERLISTSERVER] = &AdminManager::OnUserBannedFromServerListReceived;
	this->_interpreteServerMessageFct[UNBANUSER] = &AdminManager::OnUserUnbanned;
	this->_interpreteServerMessageFct[UNBANUSERSERVER] = &AdminManager::OnUserUnbannedFromServer;
	this->_interpreteServerMessageFct[SENDMESSAGE] = &AdminManager::OnMessageReceived;
	this->_interpreteServerMessageFct[EDITCHANNEL] = &AdminManager::OnEditChannel;
}

void	AdminManager::CreateUser(const std::string& login, const std::string& password)
{
	Buffer buf(login.length() + password.length() + 2);
	buf.Write((void*)login.c_str(), login.length() + 1);
	buf.Write((void*)password.c_str(), password.length() + 1);
	InfoAdmin inf;
	inf.function = CREATEUSER;
	this->SendCmd(&buf, &inf);
	
}

void	AdminManager::DeleteUser(unsigned int userId)
{
	Buffer buf(sizeof(unsigned int));
	buf.Write(&userId, sizeof(unsigned int));
	InfoAdmin inf;
	inf.function = DELETEUSER;
	this->SendCmd(&buf, &inf);
}


void	AdminManager::GetAllChannel()
{
	Buffer buf(0);
	InfoAdmin inf;
	inf.function = GETALLCHANNEL;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetAllUsers()
{
	Buffer buf(0);
	InfoAdmin inf;
	inf.function = GETALLUSER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetChannelBannedUsers(unsigned int channelId)
{
	Buffer buf(sizeof(unsigned int));
	buf.Write(&channelId, sizeof(unsigned int));
	InfoAdmin inf;
	inf.function = GETBANUSERLIST;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetBannedUsers()
{
	Buffer buf(0);
	InfoAdmin inf;
	inf.function = GETBANUSERLISTSERVER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetHostRight()
{
	Buffer buf(0);
	InfoAdmin inf;
	inf.function = GETHOSTRIGHT;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetUserHostRight(unsigned int userId)
{
	Buffer buf(sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	inf.function = GETUSERHOSTRIGHT;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::SetUserHostRight(unsigned int userId, IHostRight* hostRights)
{
	unsigned int size;
	void *data = AdminSerializer::SerializeHostRight(hostRights, size);
	Buffer buf(sizeof(int) + size);
	buf.Write(&userId, sizeof(int));
	buf.Write(data, size);
	delete data;
	InfoAdmin inf;
	inf.function = EDITUSERHOSTRIGHT;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetChannelRight(unsigned int channelId)
{
	Buffer buf(sizeof(int));
	InfoAdmin inf;
	buf.Write(&channelId, sizeof(int));
	inf.function = GETCHANNELRIGHT;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::GetUserChannelRight(unsigned int channelId, unsigned int userId)
{
	Buffer buf(2 * sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	buf.Write(&channelId, sizeof(int));
	inf.function = GETUSERCHANNELRIGHT;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::SetUserChannelRight(unsigned int channelId, unsigned int userId, IChannelRight* channelRights)
{
	unsigned int size;
	void *data = AdminSerializer::SerializeChannelRight(channelRights, size);
	Buffer buf(2 * sizeof(int) + size);
	buf.Write(&userId, sizeof(int));
	buf.Write(&channelId, sizeof(int));
	buf.Write(data, size);
	delete data;
	InfoAdmin inf;
	inf.function = EDITUSERCHANNELRIGHT;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::DeleteChannel(unsigned int channelId)
{
	Buffer buf(sizeof(int));
	InfoAdmin inf;
	buf.Write(&channelId, sizeof(int));
	inf.function = DELETECHANNEL;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::KickUserFromServer(unsigned int userId)
{
	Buffer buf(sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	inf.function = KICKUSERSERVER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::KickUser(unsigned int userId, unsigned int channelId)
{
	Buffer buf(2 * sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	buf.Write(&channelId, sizeof(int));
	inf.function = KICKUSER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::BanUserFromServer(unsigned int userId)
{
	Buffer buf(sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	inf.function = BANUSERSERVER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::BanUser(unsigned int userId, unsigned int channelId)
{
	Buffer buf(2 * sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	buf.Write(&channelId, sizeof(int));
	inf.function = BANUSER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::UnbanUserFromServer(unsigned int userId)
{
	Buffer buf(sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	inf.function = UNBANUSERSERVER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::UnbanUser(unsigned int userId, unsigned int channelId)
{
	Buffer buf(2 * sizeof(int));
	InfoAdmin inf;
	buf.Write(&userId, sizeof(int));
	buf.Write(&channelId, sizeof(int));
	inf.function = UNBANUSER;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::JoinChannel(unsigned int channelId, const std::string& password)
{
	Buffer buf(sizeof(int) + password.length() + 1);
	InfoAdmin inf;
	buf.Write(&channelId, sizeof(int));
	buf.Write((void*)password.c_str(), password.length() + 1);
	inf.function = JOINCHANNEL;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::SaveChannelChangements(IChannel *channel, bool savePassword)
{
	unsigned int size;
	InfoAdmin inf;
	AdminSerializer::ChannelInfo info;

	info.description = channel->GetDescription();
	info.motd = channel->GetMotd();
	info.name = channel->GetName();
	info.password = channel->GetPassword();
	info.maxNameLength = channel->GetMaxNameLength();
	info.maxPasswordLength = channel->GetMaxPasswordLength();
	info.maxMotdLength = channel->GetMaxMotdLength();
	info.maxDescriptionLength = channel->GetMaxDescriptionLength();
	info.visible = channel->GetVisibility();
	info.maxUser = channel->GetMaxUser();
	info.maxTalker = channel->GetMaxTalker();
	info.idParent = channel->GetIdParent();

	void * data = AdminSerializer::SerializeChannelInfo(info, size);

	Buffer buf(2 * sizeof(int) + size);
	int tmp = channel->GetId();
	buf.Write(&tmp, sizeof(int));
	tmp = savePassword ? 1 : 0;
	buf.Write(&tmp, sizeof(int));
	buf.Write(data, size);
	inf.function = EDITCHANNEL;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::SendMessageType(MsgTextType type, unsigned int id, std::string &message)
{
	unsigned int size;
	unsigned int typeInt = (int) type;
	InfoAdmin inf;

	if ((size = message.length()) > 1024)
		message[(size = 1024)] = '\0';
	Buffer buf(2 * sizeof(int) + size + 1);
	buf.Write(&typeInt, sizeof(int));
	buf.Write(&id, sizeof(int));
	buf.Write((void*)message.c_str(), size + 1);
	inf.function = SENDMESSAGE;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::SendMessageToAll(std::string &message)
{
	SendMessageType(MSGALLCHANNEL, 0, message);
}

void AdminManager::SendMessageToUser(unsigned int userId, std::string &message)
{
	SendMessageType(MSGUSER, userId, message);
}

void AdminManager::SendMessageToChannel(unsigned int chanId, std::string &message)
{
	SendMessageType(MSGCHANNEL, chanId, message);
}

void	AdminManager::AddChannel(std::string				name,
		std::string				password,
		unsigned int			maxNameLength,
		unsigned int			maxPasswordLength,
		std::string				motd,
		unsigned int			maxMotdLength,
		std::string				description,
		unsigned int			maxDescriptionLength,
		bool					visible,
		unsigned int			maxUser,
		unsigned int			maxTalker,
		unsigned int			idParent)
{
	unsigned int size;
	InfoAdmin inf;

	inf.function = CREATECHANNEL;
	AdminSerializer::ChannelInfo info;
	info.description = description;
	info.motd = motd;
	info.name = name;
	info.password = password;
	info.maxNameLength = maxNameLength;
	info.maxPasswordLength = maxPasswordLength;
	info.maxMotdLength = maxMotdLength;
	info.maxDescriptionLength = maxDescriptionLength;
	info.visible = visible;
	info.maxUser = maxUser;
	info.maxTalker = maxTalker;
	info.idParent = idParent;

	void * data = AdminSerializer::SerializeChannelInfo(info, size);
	Buffer buf(size);
	buf.Write(data, size);
	delete data;
	this->SendCmd(&buf, &inf);
}

void	AdminManager::InterpreteServerMessage(AdminFunction info, void *data, unsigned int size)
{
	(this->*(this->_interpreteServerMessageFct[info]))(data, size);
}

void	AdminManager::AddAChannel(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;
	std::list<AdminSerializer::ChannelInfo*>* lst = AdminSerializer::UnserializeChannelList((char*)serializedData, size);
	AdminSerializer::ChannelInfo* info = lst->front();
	if (!this->_channels.count(info->id))
	{
		this->_channels[info->id] = new Channel(info->id, info->idParent, info->name, info->maxNameLength,
			info->maxPasswordLength, info->motd, info->maxMotdLength, info->description, 
			info->maxDescriptionLength, info->visible, info->maxUser, info->maxTalker, info->hasPassword);
		arg.ChannelList.push_back(this->_channels[info->id]);
		this->_channels[this->_channels[info->id]->GetIdParent()]->AddChannelChild(this->_channels[info->id]);
		delete info;
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELCREATED, &arg);
	}
	delete lst;
}

void	AdminManager::TreatError(void *msg, unsigned int size)
{
	AdminEventManager::EventArg arg;

	arg.ErrorCode = *((unsigned int*) msg);
	arg.Message.assign((char*)msg + sizeof(unsigned int));
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONERROR, &arg);
}

void	AdminManager::LoadAllChannel(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;


	//Deserialisation
	std::list<AdminSerializer::ChannelInfo*>* lst = AdminSerializer::UnserializeChannelList((char*)serializedData, size);

	std::list<AdminSerializer::ChannelInfo*>::iterator it = lst->begin();
	std::list<AdminSerializer::ChannelInfo*>::iterator itend = lst->end();

	//Ajout map
	for (; it != itend; ++it)
	{
		if (!this->_channels.count((*it)->id))
		{
			this->_channels[(*it)->id] = new Channel((*it)->id, (*it)->idParent, (*it)->name, (*it)->maxNameLength,
				(*it)->maxPasswordLength, (*it)->motd, (*it)->maxMotdLength, (*it)->description, 
				(*it)->maxDescriptionLength, (*it)->visible, (*it)->maxUser, (*it)->maxTalker, (*it)->hasPassword);
			arg.ChannelList.push_back(this->_channels[(*it)->id]);
		}
		delete (*it);
	}

	//Creation arborescence
	std::map<unsigned int, IChannel*>::iterator it2 = this->_channels.begin();
	std::map<unsigned int, IChannel*>::iterator it2end = this->_channels.end();
	for (; it2 != it2end; ++it2)
	{
		this->_channels[(*it2).second->GetIdParent()]->AddChannelChild((*it2).second);
	}
	delete lst;
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELLISTRECEIVED, &arg);
}

void	AdminManager::OnUserJoinChannel(void *joinInfo, unsigned int size)
{
	AdminEventManager::EventArg arg;
	unsigned int userId = *((int *)joinInfo);
	unsigned int chanId = *((int *)joinInfo + 1);

	if ( this->_channels.count(chanId) && this->_users.count(userId))
	{
		arg.ChannelFrom = this->_channels[this->_users[userId]->GetCurrentChannelId()];
		arg.ChannelFrom->RemoveUser(this->_users[userId]);
		arg.ChannelTo = this->_channels[chanId];
		this->_users[userId]->SetCurrentChannelId(chanId);
		arg.ChannelTo->AddUser(this->_users[userId]);
		arg.UserList.push_back(this->_users[userId]);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERCHANNELCHANGE, &arg);
	}
}

void	AdminManager::OnUserDisconnection(void *joinInfo, unsigned int size)
{
	unsigned int userId = *((int *)joinInfo);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId))
	{
		arg.UserList.push_back(this->_users[userId]);
		this->_channels[this->_users[userId]->GetCurrentChannelId()]->RemoveUser(this->_users[userId]);
		this->_users[userId]->SetConnected(false);
		//this->_users.erase(userId);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERDISCONNECTION, &arg);
	}
}
void	AdminManager::OnEditChannel(void* serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;
	std::list<AdminSerializer::ChannelInfo*>* lst = AdminSerializer::UnserializeChannelList((char*)serializedData, size);
	AdminSerializer::ChannelInfo* info = lst->front();
	if (!this->_channels.count(info->id))
	{
		this->_channels[info->id] = new Channel(info->id, info->idParent, info->name, info->maxNameLength,
			info->maxPasswordLength, info->motd, info->maxMotdLength, info->description, 
			info->maxDescriptionLength, info->visible, info->maxUser, info->maxTalker, info->hasPassword);
		arg.ChannelList.push_back(this->_channels[info->id]);
		this->_channels[this->_channels[info->id]->GetIdParent()]->AddChannelChild(this->_channels[info->id]);
		delete info;
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELCREATED, &arg);
	}
	else
	{
		this->_channels[info->id]->SetName(info->name);
		this->_channels[info->id]->SetMaxNameLength(info->maxNameLength, false);
		this->_channels[info->id]->SetMaxPasswordLength(info->maxPasswordLength, false);
		this->_channels[info->id]->SetMaxMotdLength(info->maxMotdLength, false);
		this->_channels[info->id]->SetMaxDescriptionLength(info->maxDescriptionLength, false);
		this->_channels[info->id]->SetVisibility(info->visible, false);
		this->_channels[info->id]->SetMaxUser(info->maxUser, false);
		this->_channels[info->id]->SetMaxTalker(info->maxTalker, false);
		this->_channels[info->id]->SetHasPassword(info->hasPassword, false);
		this->_channels[info->id]->SetMotd(info->motd, false);
		this->_channels[info->id]->SetDescription(info->description, false);
		arg.ChannelList.push_back(this->_channels[info->id]);
		delete info;
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELEDITED, &arg);
	}
}

void	AdminManager::OnMessageReceived(void* serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;

	int fromId = *((int*)serializedData);
	AgoraCore::MsgTextType type = (AgoraCore::MsgTextType)*((int*)serializedData + 1);
	int id = *((int*)serializedData + 2);
	if (this->_users.count(fromId))
		arg.UserList.push_back(this->_users[fromId]);
	else
		return;
	if (type == AgoraCore::MSGUSER)
	{
		if (this->_users.count(id))
		{
			arg.Message = std::string((char*)serializedData + 3 * sizeof(int));
			arg.UserList.push_back(this->_users[id]);
			AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERMESSAGERECEIVED, &arg);
		}

	}
	else if (type == AgoraCore::MSGCHANNEL)
	{
		if (this->_channels.count(id))
		{
			arg.Message = std::string((char*)serializedData + 3 * sizeof(int));
			arg.ChannelList.push_back(this->_channels[id]);
			AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELMESSAGERECEIVED, &arg);
		}
	}
	else
	{
		arg.Message = std::string((char*)serializedData + 3 * sizeof(int));
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONALLCHANNELMESSAGERECEIVED, &arg);
	}

}

void	AdminManager::OnUserConnection(void* serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;

	std::list<AdminSerializer::UserInfo*>* lst = AdminSerializer::UnserializeUserList((char*)serializedData, size);

	AdminSerializer::UserInfo* info = lst->front();
	
	if (!this->_users.count(info->id))
		this->_users[info->id] = new User(info->id, info->login, info->idCurrentChannel);
	if (this->_channels.count(info->idCurrentChannel))
	{
		this->_channels[info->idCurrentChannel]->AddUser(this->_users[info->id]);
	}
	arg.UserList.push_back(this->_users[info->id]);
	delete info;
	delete lst;
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERCONNECTION, &arg);
}

void	AdminManager::LoadAllUser(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;

	std::list<AdminSerializer::UserInfo*>* lst = AdminSerializer::UnserializeUserList((char*)serializedData, size);

	std::list<AdminSerializer::UserInfo*>::iterator it = lst->begin();
	std::list<AdminSerializer::UserInfo*>::iterator itend = lst->end();

	for(; it != itend; ++it)
	{
		if (this->_users.count((*it)->id))
		{
			this->_users[(*it)->id]->SetLogin((*it)->login);
			this->_users[(*it)->id]->SetCurrentChannelId((*it)->idCurrentChannel);
		}
		else
			this->_users[(*it)->id] = new User((*it)->id, (*it)->login, (*it)->idCurrentChannel);
		this->_users[(*it)->id]->SetConnected((*it)->connected);
		if (this->_users[(*it)->id]->IsConnected() && this->_channels.count((*it)->idCurrentChannel))
		{
			this->_channels[(*it)->idCurrentChannel]->AddUser(this->_users[(*it)->id]);
		}
		arg.UserList.push_back(this->_users[(*it)->id]);
		delete (*it);
	}
	delete lst;
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERLISTRECEIVED, &arg);
}

void	AdminManager::OnUserBannedListReceived(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;
	unsigned int chanId = *((int*)serializedData);

	if (!this->_channels.count(chanId))
		return;
	arg.ChannelList.push_back(this->_channels[chanId]);
	std::list<AdminSerializer::UserInfo*>* lst = AdminSerializer::UnserializeUserList((char*)serializedData + sizeof(int), size);

	std::list<AdminSerializer::UserInfo*>::iterator it = lst->begin();
	std::list<AdminSerializer::UserInfo*>::iterator itend = lst->end();

	for(; it != itend; ++it)
	{
		if (this->_users.count((*it)->id))
		{
			this->_users[(*it)->id]->SetLogin((*it)->login);
			this->_users[(*it)->id]->SetCurrentChannelId((*it)->idCurrentChannel);
		}
		else
			this->_users[(*it)->id] = new User((*it)->id, (*it)->login, (*it)->idCurrentChannel);
		this->_users[(*it)->id]->SetConnected((*it)->connected);
		if (this->_users[(*it)->id]->IsConnected() && this->_channels.count((*it)->idCurrentChannel))
		{
			this->_channels[(*it)->idCurrentChannel]->AddUser(this->_users[(*it)->id]);
		}
		arg.UserList.push_back(this->_users[(*it)->id]);
		delete (*it);
	}
	delete lst;
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERBANNEDLISTRECEIVED, &arg);
}

void	AdminManager::OnUserBannedFromServerListReceived(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;

	std::list<AdminSerializer::UserInfo*>* lst = AdminSerializer::UnserializeUserList((char*)serializedData, size);

	std::list<AdminSerializer::UserInfo*>::iterator it = lst->begin();
	std::list<AdminSerializer::UserInfo*>::iterator itend = lst->end();

	for(; it != itend; ++it)
	{
		if (this->_users.count((*it)->id))
		{
			this->_users[(*it)->id]->SetLogin((*it)->login);
			this->_users[(*it)->id]->SetCurrentChannelId((*it)->idCurrentChannel);
		}
		this->_users[(*it)->id] = new User((*it)->id, (*it)->login, (*it)->idCurrentChannel);
		this->_users[(*it)->id]->SetConnected((*it)->connected);
		if (this->_users[(*it)->id]->IsConnected() && this->_channels.count((*it)->idCurrentChannel))
		{
			this->_channels[(*it)->idCurrentChannel]->AddUser(this->_users[(*it)->id]);
		}
		arg.UserList.push_back(this->_users[(*it)->id]);
		delete (*it);
	}
	delete lst;
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERBANNEDFROMSERVERLISTRECEIVED, &arg);
}

void	AdminManager::LoadHostRight(void* serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;

	AdminSerializer::HostRightInfo *info = AdminSerializer::UnserializeHostRight((char *)serializedData, size);

	if (this->_curUserHostRight == 0)
		this->_curUserHostRight = new HostRight();
	this->_curUserHostRight->SetHostRight(info->canChangeLogin, info->canChangePassword, info->canChangeChannel, 
					info->canCreateChannel, info->canDeleteChannel, info->canMoveChannel, 
					info->canKickUser, info->canBanUser, info->canEditUser);
	arg.UserHostRight = this->_curUserHostRight;
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONHOSTRIGHTRECEIVED, &arg);
	delete info;
}

void	AdminManager::LoadUserHostRight(void* serializedData, unsigned int size, AdminEventManager::EventName adminEvent)
{
	AdminEventManager::EventArg arg;
	unsigned int userId = *((int*)serializedData);

	serializedData = (int*)serializedData + 1;

	AdminSerializer::HostRightInfo *info = AdminSerializer::UnserializeHostRight((char *)serializedData, size);
	if (this->_users.count(userId))
	{
		if (!this->_userHostRight.count(userId))
		{
			this->_userHostRight[userId] = new HostRight();
		}
		this->_userHostRight[userId]->SetHostRight(info->canChangeLogin, info->canChangePassword, info->canChangeChannel, 
						info->canCreateChannel, info->canDeleteChannel, info->canMoveChannel, 
						info->canKickUser, info->canBanUser, info->canEditUser);
		arg.UserHostRight = this->_userHostRight[userId];
		arg.UserList.push_back(this->_users[userId]);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(adminEvent, &arg);
	}
	delete info;
}

void	AdminManager::OnUserHostRightReceived(void* serializedData, unsigned int size)
{
	LoadUserHostRight(serializedData, size, AdminEventManager::ONUSERHOSTRIGHTRECEIVED);
}

void	AdminManager::OnUserHostRightEdited(void* serializedData, unsigned int size)
{
	LoadUserHostRight(serializedData, size, AdminEventManager::ONUSERHOSTRIGHTEDITED);
}


void	AdminManager::LoadChannelRight(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;
	unsigned int chanId = *((int*)serializedData);

	serializedData = (int*)serializedData + 1;

	AdminSerializer::ChannelRightInfo* info = AdminSerializer::UnserializeChannelRight((char *)serializedData, size);

	if (this->_channels.count(chanId))
	{
		if (!this->_channelRights.count(chanId))
		{
			this->_channelRights[chanId] = new ChannelRight();
		}
		this->_channelRights[chanId]->SetChannelRight(info->canCreate, 
			info->canDelete, info->canEdit, info->canEditUser, 
			info->canTalk, info->canWrite, info->canKick, info->canBan);
		arg.ChannelRights[chanId] = this->_channelRights[chanId];
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELRIGHTRECEIVED, &arg);
	}
	delete info;
}

void	AdminManager::LoadUserChannelRight(void *serializedData, unsigned int size, AdminEventManager::EventName adminEvent)
{
	AdminEventManager::EventArg arg;
	unsigned int userId = *((int*)serializedData);
	unsigned int chanId = *((int*)serializedData + 1);

	serializedData = (int*)serializedData + 2;

	AdminSerializer::ChannelRightInfo* info = AdminSerializer::UnserializeChannelRight((char *)serializedData, size);

	if (this->_channels.count(chanId) && this->_users.count(userId))
	{
		if (!this->_userChannelRights[userId][chanId])
		{
			this->_userChannelRights[userId][chanId] = new ChannelRight();
		}
		else
		{
			AdminEventManager::EventArg arg2;
			arg.UserList.push_back(this->_users[userId]);
			arg.ChannelList.push_back(this->_channels[chanId]);
			IChannelRight* cr = this->_userChannelRights[userId][chanId];
			if (cr->GetCanTalkChannel() && !info->canTalk)
			{
				AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERMUTESOUNDCHANNEL, &arg);
			}
			else if (!cr->GetCanWriteChannel() && info->canWrite)
			{
				AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERUNMUTETXTCHANNEL, &arg);
			}
			if (cr->GetCanWriteChannel() && !info->canWrite)
			{
				AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERMUTETXTCHANNEL, &arg);
			}
			else if (!cr->GetCanTalkChannel() && info->canTalk)
			{
				AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERUNMUTESOUNDCHANNEL, &arg);
			}
			
		}

		this->_userChannelRights[userId][chanId]->SetChannelRight(info->canCreate, 
			info->canDelete, info->canEdit, info->canEditUser, 
			info->canTalk, info->canWrite, info->canKick, info->canBan);
		arg.ChannelRights[chanId] = this->_userChannelRights[userId][chanId];
		arg.UserList.push_back(this->_users[userId]);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(adminEvent, &arg);
	}
	delete info;
}

void	AdminManager::OnUserChannelRightEdited(void *serializedData, unsigned int size)
{
	LoadUserChannelRight(serializedData, size, AdminEventManager::ONUSERCHANNELRIGHTEDITED);
}

void	AdminManager::OnUserChannelRightReceived(void *serializedData, unsigned int size)
{
	LoadUserChannelRight(serializedData, size, AdminEventManager::ONUSERCHANNELRIGHTRECEIVED);
}


void	AdminManager::OnChannelDeleted(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;

	unsigned int chanId = *((int*)serializedData);
	if (this->_channels.count(chanId))
	{
		IChannel *chan = this->_channels[chanId];
		this->_channels[chan->GetIdParent()]->RemoveChannelChild(chan);
		arg.ChannelList.push_back(chan);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONCHANNELDELETED, &arg);
		this->_channels.erase(chan->GetId());
		this->_channelRights.erase(chan->GetId());
		delete chan;
	}
}

void	AdminManager::OnUserCreated(void *serializedData, unsigned int size)
{
	AdminEventManager::EventArg arg;
	std::list<AdminSerializer::UserInfo*>* lst = AdminSerializer::UnserializeUserList((char*)serializedData, size);

	AdminSerializer::UserInfo *info = lst->front();

	this->_users[info->id] = new User(info->id, info->login, info->idCurrentChannel);
	arg.UserList.push_back(this->_users[info->id]);
	AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERCREATION, &arg);
	delete lst;
}
void	AdminManager::OnUserKicked(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId))
	{
		arg.UserList.push_back(this->_users[userId]);
		this->_channels[this->_users[userId]->GetCurrentChannelId()]->RemoveUser(this->_users[userId]);
		this->_channels[0]->AddUser(this->_users[userId]);
		this->_users[userId]->SetCurrentChannelId(0);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERKICKED, &arg);
	}
}

void	AdminManager::OnUserKickedFromServer(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId))
	{
		arg.UserList.push_back(this->_users[userId]);
		this->_users[userId]->SetConnected(false);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERKICKEDFROMSERVER, &arg);
	}
}

void	AdminManager::OnUserUnbanned(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	unsigned int chanId = *((int *)serializedData + 1);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId) && this->_channels.count(chanId))
	{
		arg.UserList.push_back(this->_users[userId]);
		arg.ChannelList.push_back(this->_channels[chanId]);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERUNBANNED, &arg);
	}
}

void	AdminManager::OnUserUnbannedFromServer(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId))
	{
		arg.UserList.push_back(this->_users[userId]);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERUNBANNEDFROMSERVER, &arg);
	}
}

void	AdminManager::OnUserBanned(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	unsigned int chanId = *((int *)serializedData + 1);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId) && this->_channels.count(chanId))
	{
		
		arg.UserList.push_back(this->_users[userId]);
		arg.ChannelList.push_back(this->_channels[chanId]);
		if (this->_users[userId]->GetCurrentChannelId() == chanId && this->_channels.count(0))
		{
			arg.ChannelFrom = this->_channels[chanId];
			arg.ChannelFrom->RemoveUser(this->_users[userId]);
			arg.ChannelTo = this->_channels[0];
			this->_users[userId]->SetCurrentChannelId(0);
			arg.ChannelTo->AddUser(this->_users[userId]);
			AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERCHANNELCHANGE, &arg);
		}
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERBANNED, &arg);
	}
}

void	AdminManager::OnUserBannedFromServer(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId))
	{
		arg.UserList.push_back(this->_users[userId]);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERBANNEDFROMSERVER, &arg);
	}
}


void	AdminManager::OnUserDeleted(void *serializedData, unsigned int size)
{
	unsigned int userId = *((int *)serializedData);
	AdminEventManager::EventArg arg;

	if (this->_users.count(userId))
	{
		arg.UserList.push_back(this->_users[userId]);
		this->_channels[this->_users[userId]->GetCurrentChannelId()]->RemoveUser(this->_users[userId]);
		this->_users.erase(userId);
		AdminEventManager::GetAdminEventManager()->LaunchEvent(AdminEventManager::ONUSERDELETED, &arg);
		delete arg.UserList.front();
	}
}

void	AdminManager::SendCmd(IBuffer* buf, InfoAdmin* inf)
{
	this->_agora->EmpackedBufferTxtAdm(buf, inf);
}

void	AdminManager::ClearData()
{
	
	std::map<unsigned int, IChannel*>::iterator it	= _channels.begin();
	std::map<unsigned int, IChannel*>::iterator itend	= _channels.end();
	for(; it != itend; ++it)
	{
		delete it->second;
	}


	std::map<unsigned int, IUser*>::iterator ituser	= _users.begin();
	std::map<unsigned int, IUser*>::iterator ituserend	= _users.end();
	for(; ituser != ituserend; ++ituser)
	{
		delete ituser->second;
	}

	std::map<unsigned int, IChannelRight*>::iterator itcright	= _channelRights.begin();
	std::map<unsigned int, IChannelRight*>::iterator itcrightend	= _channelRights.end();
	for(; itcright != itcrightend; ++itcright)
	{
		delete itcright->second;
	}


	delete _curUserHostRight;

	std::map<unsigned int, std::map<unsigned int, IChannelRight*> >::iterator itucright	= _userChannelRights.begin();
	std::map<unsigned int, std::map<unsigned int, IChannelRight*> >::iterator itucrightend	= _userChannelRights.end();
	for(; itucright != itucrightend; ++itucright)
	{
		itcright	= itucright->second.begin();
		itcrightend	= itucright->second.end();
		for(; itcright != itcrightend; ++itcright)
		{
			delete itcright->second;
		}
	}
	
	std::map<unsigned int, IHostRight*>::iterator ituhost	= _userHostRight.begin();
	std::map<unsigned int, IHostRight*>::iterator ituhostend	= _userHostRight.end();
	for(; ituhost != ituhostend; ++ituhost)
	{
		delete ituhost->second;
	}


	_channels.clear();
	_users.clear();
	_channelRights.clear();
	_curUserHostRight = 0;
	_userChannelRights.clear();
	_userHostRight.clear();
}
